<script setup>
import { onMounted, onUnmounted, ref, reactive } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";

import mainPoinData from "./data/coordinate.json";//主要途径点
import lczData from "./data/lcz.json";//里程桩


//是否开启测距
let isRuler = ref(true);
//是否显示里程桩
let isShowLcz = ref(false);
//是否显示路径
let isShowPath = ref(false);
//是否编辑路径
let isEditPath = ref(false);
//是否显示车道
let isShowLane = ref(false);

let lczNum = ref(54);//里程桩
let jiaNum = ref(153);//应加距离

let distanceLast = ref(0);//距离上个节点的距离
let lnglat1Div = ref('');//经纬度样式1
let lnglat2Div = ref('');//经纬度样式2
let lineWidth = ref(20);//路径宽度

let map = null;
let AMap = null;
let mouseInfo;//测距过程中,鼠标移动时显示的信息窗体
let ruler;//测距工具
let lczMKList = [];//里程桩Marker
//画线-车道
let lanePolyline;
//画线-路径
let pathPolyline;
let lczPointArray = [];//坐标点的二维数组
let lczPointKV = {};//坐标点的键值对
let polylineEditor;//路径编辑器
let rangeArr = [];//记录所有的标注点
let isMeasue = false;//是否测量中
let infoOptions;//鼠标移动时,显示距离的信息窗体


/*----------------开启或关闭测距--------------*/
function rulerOnClick() {
  isRuler.value = !isRuler.value;
  rulerOn(isRuler);
}

function rulerOn(flag) {
  if (isRuler.value) {
    ruler.turnOn();
  } else {
    ruler.turnOff();
    if (mouseInfo) mouseInfo.close();
  }
}

/*----------------显示或隐藏里程桩--------------*/
function showLcz() {
  isShowLcz.value = !isShowLcz.value;
  showLczOn(isShowLcz.value);
}
function showLczOn(flag) {
  if (flag) {
    map.add(lczMKList);
  } else {
    map.remove(lczMKList);
  }
}

/*----------------显示或隐藏路径--------------*/
function showPath() {
  isShowPath.value = !isShowPath.value;
  showPathOn(isShowPath.value);
}
function showPathOn(flag) {
  if (flag) {
    map.add(pathPolyline);
  } else {
    map.remove(pathPolyline);
  }
}


/*----------------加载数据--------------*/
function reLoadData() {
  lczPointArray = [];
  let str1 = '', str2 = '';
  for (let key in lczPointKV) {
    let point = lczPointKV[key];
    lczPointArray.push([point.lng, point.lat]);

    str1 += `"${key}":{"lng":${point.lng},"lat":${point.lat}},<br>`;
    str2 += `[${point.lng},${point.lat}],<br>`;
  }
  //样式一
  lnglat1Div.value = str1;
  //样式二
  lnglat2Div.value = str2;
}


/*----------------编辑路径--------------*/
function editPath() {
  isEditPath.value = !isEditPath.value;
  editPathOn(isEditPath.value);
}
function editPathOn(flag) {
  if (flag) {
    polylineEditor.open();
  } else {
    polylineEditor.close();
  }
}

/*------------------清空数据--------------------*/
function clearData() {
  lnglat1Div.value = '';
  lnglat2Div.value = '';
  rangeArr = [];
  isMeasue = false;
  // lczSum = parseInt(document.getElementById('lcz').value);
  // jiaSum = parseInt(document.getElementById('jia').value);;
  infoOptions.closeWhenClickMap = true
  if (mouseInfo) mouseInfo.close();  //关闭信息窗体
}

/*----------------显示或隐藏车道--------------*/
function showLane() {
  isShowLane.value = !isShowLane.value;
  showLaneOn();
}
function showLaneOn() {
  if (isShowLane.value) {
    map.getZoom() > 19.5 ? map.add(lanePolyline) : map.remove(lanePolyline);
  } else {
    map.remove(lanePolyline);
  }
}


/*----------------应用路径宽度--------------*/
function applayLineWidth() {
  pathPolyline.setOptions({
    strokeWeight: lineWidth.value
  });
}



onMounted(() => {

  AMapLoader.load({
    key: "a6c9b18ee934604615f41aabe312ae64", // 申请好的Web端开发者Key，首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    plugins: ["AMap.Scale", "AMap.MapType", "AMap.ToolBar", 'AMap.RangingTool', 'AMap.MouseTool', 'AMap.MapType', 'AMap.PolylineEditor'], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
  }).then((aMap) => {
    AMap = aMap;


    map = new AMap.Map("container", {
      // 设置地图容器id
      viewMode: "3D", // 是否为3D地图模式 
      zoom: 10, // 初始化地图级别
      center: [116.443642, 36.058487], // 初始化地图中心点位置
    });

    map.addControl(new AMap.Scale()); //添加比例尺组件到地图实例上
    map.addControl(new AMap.ToolBar());//缩放平移工具条
    //地图类型切换
    map.addControl(new AMap.MapType({
      defaultType: 0
    }));


    //测距工具
    ruler = new AMap.RangingTool(map, {
      lineOptions: {
        // strokeColor: "#FF33FF",
        strokeOpacity: 1,
        strokeWeight: 1,
        strokeStyle: "solid",
        strokeDasharray: [10, 5],
      },
      tmpLineOptions: {
        strokeColor: "#FF33FF",
        strokeOpacity: 1,
        strokeWeight: 1,
        strokeStyle: "solid",
        strokeDasharray: [10, 5],
      },
    });

    rulerOn(isRuler);

    /*
     * 测距过程中,添加途经点
     */
    //里程桩和应加距离的临时变量,用于鼠标移动时显示
    let lczSumTemp = lczNum.value;
    let jiaSumTemp = jiaNum.value;

    let nodeIndex = 1;
    ruler.on('addnode', (e) => {
      isMeasue = true;

      rangeArr.push([e.position.lng, e.position.lat]);

      //距离上个点的距离
      // let distanceLast = 0;
      distanceLast.value = 0;
      if (rangeArr.length > 1) {
        //距离上个点
        distanceLast.value = AMap.GeometryUtil.distance(rangeArr[rangeArr.length - 2], rangeArr[rangeArr.length - 1]);
        jiaNum.value += Math.round(distanceLast.value);//四舍五入
      }

      distanceLast.value = distanceLast.value.toFixed(2);

      //大于1000米，里程桩+n
      if (jiaNum.value >= 1000) {
        lczNum.value += Math.floor(jiaNum.value / 1000);
        jiaNum.value = jiaNum.value % 1000;
      }
      lczSumTemp = lczNum.value;
      jiaSumTemp = jiaNum.value;

      /*--------------页面显示经纬度的json--------------*/
      //样式一
      //获取已有数据,上一行增加逗号或换行符
      let str = lnglat1Div.value;
      if (str != '') {
        //上一个节点最后增加逗号
        str = str.slice(0, -4);
        str += ',<br>';

        //非第一次测距的起点,增加一个换行符
        if (rangeArr.length == 1 && nodeIndex > 1) {
          str += '<br>';
        }
      }
      str += `"K${lczNum.value}+${jiaNum.value}":{"lng":${e.position.lng},"lat":${e.position.lat}}<br>`;
      lnglat1Div.value = str;

      //样式二
      lnglat2Div.value += `[${e.position.lng},${e.position.lat}],<br>`;

      nodeIndex++;
    });



    //鼠标移动时,显示距离
    infoOptions = {
      anchor: 'top-left',
      closeWhenClickMap: false,
      offset: new AMap.Pixel(5, 5)
    };
    map.on('mousemove', (e) => {
      if (isMeasue) {
        //距离上个点
        let distanceMiddle = AMap.GeometryUtil.distance(rangeArr[rangeArr.length - 1], [e.lnglat.lng, e.lnglat.lat]);
        //当前应加距离
        jiaSumTemp = jiaNum.value + Math.round(distanceMiddle);//四舍五入
        //大于1000米，里程桩+n
        if (jiaSumTemp >= 1000) {
          lczSumTemp = lczNum.value + Math.floor(jiaSumTemp / 1000);
          jiaSumTemp = jiaSumTemp % 1000;
        } else {
          lczSumTemp = lczNum.value;
        }

        infoOptions.content = `${distanceMiddle.toFixed(2)}米<br>K${lczSumTemp}+${jiaSumTemp}`;
        mouseInfo = new AMap.InfoWindow(infoOptions);
        mouseInfo.open(map, e.lnglat);
      }
    });
    //捕捉右键事件,测距结束,关闭信息窗体
    map.on('rightclick', (e) => {
      endRuler(e);
    });
    //测距结束
    ruler.on('end', (e) => {
      endRuler(e);
    });
    function endRuler(e) {
      if (isMeasue) {
        isMeasue = false
        rangeArr = [];
        infoOptions.closeWhenClickMap = true
        mouseInfo.close();  //关闭信息窗体
      }
    }

    //主要途径点
    let mainMKList = [];

    // fetch('config/coordinate.json').then(response => response.json())
    //   .then(data => {
    for (let key in mainPoinData) {
      let point = mainPoinData[key];
      let marker = new AMap.Marker({
        position: new AMap.LngLat(point.lng, point.lat),
        label: {
          content: `${point.name + point.code}`,
        }
      });
      mainMKList.push(marker);
    }
    map.add(mainMKList);
    // }).catch(error => {
    //   console.error('Error:', error);
    // });

    /*------------------可移动点------------------*/
    // //开始点
    // var startMarker = new AMap.Marker({
    //   position: new AMap.LngLat(116.86085,36.578567)
    // });
    // startMarker.on('click', onMarkerClick); // 绑定 click 事件
    // map.add(startMarker);
    // 创建marker点击后的信息窗体
    let infoWindow = new AMap.InfoWindow({
      isCustom: true,  // 使用自定义窗体
      content: '<div class="marker_info_window" style="font-size: 12px;background-color: #fff;border: 1px solid #ccc;border-radius: 4px;color: crimson;padding: 3px;">可移动点位</div>',
      offset: new AMap.Pixel(20, -30)
    });
    let lastDragMarker;//最后一个可移动的点
    // let lastDragMarkerLnglat;//最后一个可移动的点的经纬度
    let lastDragLczKey;//最后一个被拖拽的里程桩的key
    let onMarkerClick = function (e) {
      //关闭上一个点的可移动效果
      lastDragMarker && lastDragMarker.setDraggable(false);
      infoWindow.open(map, e.target.getPosition()); // 打开信息窗体
      this.setDraggable(true);
      // e.target 就是被点击的 Marker
      //点击不同点,才更新数据
      if (lastDragMarker == undefined || lastDragMarker._amap_id != e.target._amap_id) {
        lastDragMarker = e.target;
        lastDragLczKey = findLcz([e.target.getPosition().lng, e.target.getPosition().lat]);
      }
    }

    let onMarkerDragging = function (e) {
      infoWindow.open(map, e.target.getPosition()); // 更新信息窗体的位置
    }

    let onMarkerDragend = function (e) {
      //更新数据
      lczPointKV[lastDragLczKey].lng = e.target.getPosition().lng;
      lczPointKV[lastDragLczKey].lat = e.target.getPosition().lat;
      reLoadData();

      pathPolyline.setPath(lczPointArray);

      //编辑路径模式下,拖拽点后,重新打开编辑器,否则编辑器不会更新
      if (isEditPath.value) {
        polylineEditor.close();
        polylineEditor.open();
      }

    }

    //根据坐标点,查找历史数据中的里程桩
    function findLcz(lnglat) {
      let lczKey = '';
      for (let key in lczPointKV) {
        let point = lczPointKV[key];
        if (point.lng == lnglat[0] && point.lat == lnglat[1]) {
          lczKey = key;
          break;
        }
      }
      return lczKey;
    }

    /*------------------加载数据--------------------*/
    /*---------------加载里程桩数据----------------*/
    for (let key in lczData) {
      let point = lczData[key];
      let marker = new AMap.Marker({
        position: new AMap.LngLat(point.lng, point.lat),
        label: {
          content: `${key}`,
        }
      });
      marker.on('click', onMarkerClick); // 绑定 click 事件
      marker.on('dragging', onMarkerDragging);// 绑定点在移动的过程中事件
      marker.on('dragend', onMarkerDragend);// 绑定点在移动结束事件

      lczMKList.push(marker);
      lczPointArray.push([point.lng, point.lat]);
    }
    //@TODO:这里可以优化
    lczPointKV = lczData;

    //显示/隐藏里程桩
    showLczOn(isShowLcz.value);

    //画车道,只画出来,不显示,鼠标放大到一定级别显示
    createPath();

    //画路径
    drawingLine(lczPointArray, 0, lineWidth.value, "#00B3CC");
    showPathOn(isShowPath.value);



    /*----------------编辑路径--------------*/


    // 编辑器
    polylineEditor = new AMap.PolylineEditor(map, pathPolyline);
    // 开启/关闭编辑模式
    editPathOn(isEditPath.value);

    polylineEditor.on('adjust', function (event) {
      console.log('adjust');
      console.log(event);
    });

    /*----------------画线(路径)方法--------------*/
    function drawingLine(datas, borderWeight = 1, strokeWeight = 0) {
      pathPolyline = new AMap.Polyline({
        path: datas,
        isOutline: true,
        outlineColor: "#3366FF",//轮廓线颜色
        borderWeight: borderWeight,//轮廓线宽度
        strokeWeight: strokeWeight, // 线宽
        strokeColor: '#3366FF',   // 线颜色
        // strokeColor: "#3366FF",
        strokeOpacity: 0.3,// 线透明度
        strokeStyle: "solid",// 折线样式还支持 'dashed'
        // strokeStyle是dashed时有效
        // strokeDasharray: [10, 5],
        lineJoin: "round",
        lineCap: "round",
        zIndex: 50
      });
    }


    /*----------------创建图片图层--------------*/
    // var imageLayer = new AMap.ImageLayer({
    //   // url: 'https://amappc.cn-hangzhou.oss-pub.aliyun-inc.com/lbs/static/img/dongwuyuan.jpg',
    //   url: './images/chedao.png',
    //   bounds: new AMap.Bounds(
    //     [116.794139, 36.555254],
    //     [116.787085, 36.540404]
    //   ),
    //   zooms: [15, 20]
    // });

    // // 将图层添加至地图实例
    // map.add(imageLayer);





    /*----------------地图缩放事件,缩放到一定级别显示道路--------------*/
    function createPath() {
      lanePolyline = new AMap.Polyline({
        path: lczPointArray,            // 设置线覆盖物路径
        showDir: true,
        dirImg: createCanvas(),
        zIndex: 9,
        isOutline: true,
        outlineColor: '#C4C6C7',
        borderWeight: 2,//轮廓线宽度
        strokeOpacity: 1,         // 线透明度
        strokeStyle: "solid",
        // strokeDasharray: [10, 2, 10],
        strokeColor: '#394851',   // 线颜色
        strokeWeight: 60           // 线宽
      });
    }

    function createCanvas() {
      let canvasDir = document.createElement('canvas')
      let width = 150;
      let height = 150;

      canvasDir.width = width;
      canvasDir.height = height;
      var context = canvasDir.getContext('2d');
      context.strokeStyle = '#C4C6C7';
      context.lineJoin = 'round';
      context.lineWidth = 5;

      //左边实线
      // context.moveTo(5, 0);
      // context.lineTo(5, height);
      //左边虚线
      context.moveTo(35, 0);
      context.lineTo(35, 50);
      context.moveTo(35, 100);
      context.lineTo(35, 150);
      //中间虚线
      context.moveTo(75, 20);
      context.lineTo(75, 70);
      context.moveTo(75, 120);
      context.lineTo(75, 170);
      //右边虚线
      context.moveTo(115, 0);
      context.lineTo(115, 50);
      context.moveTo(115, 100);
      context.lineTo(115, 150);
      //最右侧实线
      // context.moveTo(width - 5, 0);
      // context.lineTo(width - 5, height);

      context.stroke();

      // 绘制一个填充矩形
      // context.fillStyle = "red";
      // context.fillRect(0, 0, width, height);

      return canvasDir;
    }


    map.on('zoomchange', () => {
      showLaneOn();
    });



  }).catch((e) => {
    console.log(e);
  });



});

onUnmounted(() => {
  map?.destroy();
});
</script>

<template>
  <div id="container"></div>

  <div id='right'>
    <div>
      <div class='title'>选择功能</div>
      <div>
        <button @click="rulerOnClick" :class="isRuler ? 'btnOn' : 'btnOff'">开启测距</button>
        <button @click="reLoadData">加载数据</button>
        <button @click="showLcz" :class="isShowLcz ? 'btnOn' : 'btnOff'">显示里程桩</button>
        <button @click="clearData">清空数据</button>
      </div>
      <div>
        <button @click="showPath" :class="isShowPath ? 'btnOn' : 'btnOff'">显示路径</button>
        路径宽度:
        <input type="number" v-model="lineWidth" onfocus="this.select();">
        <input type="number" style="display:none;">
        <button @click="applayLineWidth">应用</button>
        <button @click="editPath" :class="isEditPath ? 'btnOn' : 'btnOff'">编辑路径</button>
        <button @click="showLane" :class="isShowLane ? 'btnOn' : 'btnOff'">显示车道</button>
      </div>
    </div>
    <div>
      <div class='title'>选址结果</div>
      <div>起始点:</div>
      <div class="content">
        里程桩:K<input type="number" v-model="lczNum" onfocus="this.select();">
            加:<input type="number" v-model="jiaNum" onfocus="this.select();">
      </div>
      <br>

      <div>当前距离:</div>
      <div class="content">
        距离上个节点:<span v-html="distanceLast"></span>米
        <!-- 加:<span id="jiaSum">0</span>米 -->
      </div>
      <br>

      <div>当前缩放级别:&nbsp;&nbsp;<span id="zoom"></span></div><br>

      <div>经纬度样式1:</div>
      &nbsp;{
      <div v-html='lnglat1Div' class="content"></div>
      &nbsp;}

      <br><br>

      <div>经纬度样式2:</div>
      &nbsp;[
      <div v-html='lnglat2Div' class="content"></div>
      &nbsp;]<br>
    </div>
  </div>
</template>

<style scoped>
#container {
  width: 80%;
  height: 100%;
  float: left;
}

#right {
  color: #444;
  background-color: #f8f8f8;
  width: 20%;
  float: left;
  height: 100%;
}

/* .amap-icon img,
    .amap-marker-content img {
      width: 25px;
      height: 34px;
    } */

.marker_info_window {
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 4px;
  color: crimson;
  padding: 3px;
}

.title {
  width: 100%;
  background-color: #dadada;
  padding-left: 15px;
}

/* #onRuler,
    #offRuler, */
#right input,
button {
  margin: 4px;
}

#right input {
  width: 80px;
}

.content {
  padding-left: 15px;
  max-height: 390px;
  overflow-y: scroll;
  /* overflow-x: hidden; */
}

.content::-webkit-scrollbar {
  width: 10px;
  /* 滚动条宽度 */
  background-color: #F5F5F5;
  /* 背景颜色 */
}

.content::-webkit-scrollbar-thumb {
  background-color: #555;
  /* 滚动条正常状态颜色 */
}

.content::-webkit-scrollbar-thumb:hover {
  background-color: #000;
  /* 滚动条悬停状态颜色 */
}

/*button点击之后的样式*/
.btnOn {
  background-color: #1E90FF;
  color: #fff;
}

button,
.btnOff {
  background-color: #fff;
  color: #000;
}

button:active {
  background-color: #1E90FF;
  color: #fff;
}

textarea {
  width: 98%;
}
</style>
